/*
 * @Author: your name
 * @Date: 2021-05-22 20:57:29
 * @LastEditTime: 2021-05-22 21:10:00
 * @LastEditors: Please set LastEditors
 * @Description: In User Settings Edit
 * @FilePath: /ewebengine/simulator/monit.c
 */
// 1.获取输出路径和输入路径
// 2.启动线程监控输入路径
// 3.根据md5或者文件修改时间判断文件是否修改
// 4.如发生变化，则调用系统shell命令python3 nxp.py ./xxx ./xxx
// 5.刷新当前页面

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <stdbool.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <pthread.h>
#include "md5.h"

extern int test_main(int argc, char *argv[]);

static char *src_dir = NULL; // evue directory
static char *conf_file = NULL; // nxp guide config file

#define MD5_LENGTH 16

static uint8_t last_modify_md5[MD5_LENGTH] = {0};
static long last_modidy_ts = 0;

// 判断md5值是否合法
bool md5_check(uint8_t *msg, uint32_t msg_length, uint8_t *md5) {
    bool result = false;

    int res = strncmp((const char *)msg, (const char *)md5, msg_length);
    if (res == 0) result = true;
    return result;
}

char * ReadFile(char * path, int *length)
{
    FILE * pfile;
    char * data;

    pfile = fopen(path, "rb");
    if (pfile == NULL)
    {
        return NULL;
    }
    fseek(pfile, 0, SEEK_END);
    *length = ftell(pfile);
    data = (char *)malloc((*length + 1) * sizeof(char));
    rewind(pfile);
    *length = fread(data, 1, *length, pfile);
    data[*length] = '\0';
    fclose(pfile);
    return data;
}


int GetFileModifyTime(char * fpath)
{
    FILE * fp;
    int fd;
    struct stat buf;
    fp = fopen(fpath, "r");
    if(NULL != fp )
    {
        fd = fileno(fp);
        fstat(fd, &buf);
        int size = buf.st_size; // get file size (byte)
        long modify_time = buf.st_mtime; // latest modification time (seconds passed from 01/01/00:00:00 1970 UTC)
        printf("size = %d\n",size);
        printf("modify_time = %ld\n", modify_time);
        fclose(fp);
        return modify_time;
    }
    printf("function error\n");
    return 0;
}

void monit_init(int argc, char *argv[]){
    int i = 0;
    char *arg_name;
    char *arg_value;

    if( argc > 1 ) {
        for(i = 1; i < argc; i += 2) {
            arg_name = argv[i];
            arg_value = argv[i + 1];

            if( !strcmp(arg_name, "--src") ) {
                src_dir = arg_value;
            } else if( !strcmp(arg_name, "--dst") ) {
                conf_file = arg_value;
            }
        }
    }
}

// 执行系统命令代码
int generate_code() {
    int ret = 0;
    char * string = "ls -al";
//    char *cmd_string = "python3 script.py %s %s";
//    char string[strlen(cmd_string) + strlen(src_dir) + strlen(conf_file)];
//    sprintf(string, cmd_string, conf_file, src_dir);
    printf("%s\r\n", string);
    ret = system(string);
    return ret;
}

// refresh 刷新页面
void refresh_page() {
    printf("检测到文件已经发生改变\r\n");
}

// 监控目录
void * monit_dir(void *params) {
    (void)params;

    while(1) {
        // 获取当前目录修改时间
        long mts = GetFileModifyTime(conf_file);

        printf("%s\r\n", conf_file);

        printf("timestamp:%lu -- %lu\r\n", mts, last_modidy_ts);
        // 如果发生改变，则调用python重新生成evue文件
        if (mts != last_modidy_ts) {
            last_modidy_ts = mts;

            int file_len = 0;
            char * data = ReadFile(conf_file, &file_len);

            MD5_CTX md5;
            MD5Init(&md5);

            MD5Update(&md5, (uint8_t *)data, file_len);
            char tmp[MD5_LENGTH];
            MD5Final(&md5, (uint8_t *)&tmp);

//            bool result = md5_check((uint8_t *)data, file_len, last_modify_md5);
            bool result = memcmp(tmp, last_modify_md5, MD5_LENGTH);

            printf("==============> %d\r\n", result ? 10: 100);

            if (result) {
//                generate_code();
                refresh_page();
            }
            free(data);

            memcpy(last_modify_md5, tmp, MD5_LENGTH);
        }

        for(int i=0;i<MD5_LENGTH;i++)
        {
            printf("%02x", last_modify_md5[i]);
        }
        printf("\r\n");

        // 睡眠1秒钟
        sleep(1);
    }

#ifndef IS_DETACHED
     pthread_detach(pthread_self());
#endif
}

void init() {
    memset(last_modify_md5, 0, MD5_LENGTH);
}

void monit_main(int argc, char *argv[]) {
    init();
    monit_init(argc, argv);

    if (src_dir != NULL && conf_file != NULL) {
        monit_init(argc, argv);
        // 启动一个线程
        pthread_t thread;
#ifdef IS_DETACHED
        pthread_attr_t attr;
        pthread_attr_init( &attr );
        pthread_attr_setdetachstate(&attr,1);
        pthread_create(&thread, &attr, monit_dir, 0); // 第二个参数决定了分离属性
#else
        pthread_create(&thread, NULL, monit_dir, 0);
//        monit_dir(0);
#endif
        // 需要等待的线程,指定的线程必须位于当前的进程中，而且不得是分离线程
        // 线程tid所执行的函数返回值（返回值地址需要保证有效），其中status可以为NULL
#ifndef IS_DETACHED
        pthread_join(thread, NULL);
#endif
    } else {
        printf("请检查参数是否输入正确！\r\n");
        test_main(argc, argv);

    }
}

int main(int argc, char *argv[]) {
    monit_main(argc, argv);
}
